//
//  WPieChartView.m
//  WPieChart
//
//  Created by winter on 16/1/5.
//  Copyright © 2016年 winter. All rights reserved.
//

#import "WPieChartView.h"
#import <math.h>

#define RADIUS_MARGIN   20

@interface WPieChartView ()

@property (nonatomic) NSArray *endPercentages;

@property (nonatomic) CAShapeLayer *pieLayer;

/** Default is 1.0. */
@property (nonatomic) NSTimeInterval duration;
@end

@implementation WPieChartView

- (instancetype)initWithFrame:(CGRect)frame items:(NSArray<WPieChartDataItem *> *)items
{
    self = [self initWithFrame:frame];
    if (!self) {
        self.items = items;
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self bootstrap];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self bootstrap];
    }
    return self;
}

- (void)bootstrap
{
    self.backgroundColor = [UIColor clearColor];
    self.concentric = YES;
    self.duration = 1.0;
    self.displayAnimated = YES;
}

- (void)setItems:(NSArray<WPieChartDataItem *> *)items
{
    _items = items;
    [self loadDefault];
}

- (void)setConcentric:(BOOL)concentric
{
    _concentric = concentric;
    
    if (concentric) {
        self.outerCircleRadius  = MIN(self.bounds.size.width, self.bounds.size.height) / 2;
        self.innerCircleRadius  = self.outerCircleRadius - RADIUS_MARGIN;
    }
    else {
        self.outerCircleRadius  = MIN(self.bounds.size.width, self.bounds.size.height) / 2;
        self.innerCircleRadius  = 1;
    }
}

/* Redraw the chart on autolayout */
-(void)layoutSubviews
{
    [super layoutSubviews];
    [self loadDefault];
}

#pragma mark - private method

- (WPieChartDataItem *)dataItemForIndex:(NSInteger)index
{
    return self.items[index];
}

- (CGFloat)startPercentageForItemAtIndex:(NSInteger)index
{
    if (index == 0) {
        return 0;
    }
    return [self.endPercentages[index - 1] floatValue];
}

- (CGFloat)endPercentageForItemAtIndex:(NSInteger)index
{
    return [self.endPercentages[index] floatValue];
}

- (void)addPieChartItem:(WPieChartDataItem *)item
{
//    WPieChartDataItem *value = [[WPieChartDataItem alloc] init];
//    value.angle = angle;
//    value.color = color;
//
//    [self.valuesAndColors addObject:value];
//    [self setNeedsDisplay];
}

- (void)insertPieChartItem:(WPieChartDataItem *)item atIndex:(NSInteger)index
{
//    WPieChartDataItem *value = [[WPieChartDataItem alloc] init];
//    value.angle = angle;
//    value.color = color;
//
//    [self.valuesAndColors insertObject:value atIndex:index];
//    [self setNeedsDisplay];
}

- (void)amplifyPieChartWithIndex:(NSInteger)index amplifyValue:(CGFloat)amplifyValue
{
//    if (index > self.valuesAndColors.count -1) {
//        NSLog(@"error : %s -- index %ld beyond bounds array",__func__, (long)index);
//        return;
//    }
//
//    [self.valuesAndColors enumerateObjectsUsingBlock:^(WPieChartDataItem * obj, NSUInteger idx, BOOL * _Nonnull stop) {
//        if (idx == index) {
//            obj.amplifyValue = amplifyValue;
//        }
//        else {
//            obj.amplifyValue = 0;
//        }
//    }];
//    
//    [self setNeedsDisplay];
}

- (void)loadDefault
{
    NSInteger itemCount = self.items.count;
    if (itemCount == 0) {
        return;
    }
    
    __block CGFloat currentTotal = 0;
    CGFloat total = [[self.items valueForKeyPath:@"@sum.value"] floatValue];
    NSMutableArray *endPercentages = [NSMutableArray arrayWithCapacity:itemCount];
    [self.items enumerateObjectsUsingBlock:^(WPieChartDataItem *obj, NSUInteger idx, BOOL *stop) {
        if (total == 0) {
            [endPercentages addObject:@(1.0 / itemCount * (idx + 1))];
        }
        else {
            currentTotal += obj.value;
            [endPercentages addObject:@(currentTotal / total)];
        }
    }];
    self.endPercentages  = [endPercentages copy];
    self.pieLayer = [CAShapeLayer layer];
    [self.layer addSublayer:self.pieLayer];
    
    [self strokeChart];
}

#pragma mark - drawing method

// 画表
- (void)strokeChart
{
    WPieChartDataItem *currentItem;
    for (int i = 0; i < self.items.count; i++) {
        currentItem = [self dataItemForIndex:i];
        
        CGFloat startPercentage = [self startPercentageForItemAtIndex:i];
        CGFloat endPercentage = [self endPercentageForItemAtIndex:i];
        
        CGFloat radius = self.innerCircleRadius + (self.outerCircleRadius - self.innerCircleRadius) / 2.0;
        CGFloat borderWidth =  self.outerCircleRadius - self.innerCircleRadius;
        
        CAShapeLayer *currenPieLayer = [self newCircleLayerWithRadius:radius
                                                          borderWidth:borderWidth
                                                            fillColor:[UIColor clearColor]
                                                          borderColor:currentItem.color
                                                      startPercentage:startPercentage
                                                        endpercentage:endPercentage];
        [self.pieLayer addSublayer:currenPieLayer];
    }

    [self maskChart];
    [self addAnimationIfNeeded];
}


- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
                               borderWidth:(CGFloat)borderWidth
                                 fillColor:(UIColor *)fillColor
                               borderColor:(UIColor *)borderColor
                           startPercentage:(CGFloat)startPercentage
                             endpercentage:(CGFloat)endPercentage
{
    CAShapeLayer *circle = [CAShapeLayer layer];
    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
                                                        radius:radius
                                                    startAngle:-M_PI_2
                                                      endAngle:M_PI_2 * 3
                                                     clockwise:YES];
    circle.fillColor = fillColor.CGColor;
    circle.strokeColor = borderColor.CGColor;
    circle.strokeStart = startPercentage;
    circle.strokeEnd = endPercentage;
    circle.lineWidth = borderWidth;
    circle.path = path.CGPath;
    
    return circle;
}

- (void)maskChart
{
    CGFloat radius = self.innerCircleRadius + (self.outerCircleRadius - self.innerCircleRadius) / 2.0;
    CGFloat borderWidth =  self.outerCircleRadius - self.innerCircleRadius;
    CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:radius
                                                 borderWidth:borderWidth
                                                   fillColor:[UIColor clearColor]
                                                 borderColor:[UIColor blackColor]
                                             startPercentage:0
                                               endpercentage:1];
    self.pieLayer.mask = maskLayer;
}

- (void)addAnimationIfNeeded
{
    if (self.displayAnimated) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        animation.duration = self.duration;
        animation.fromValue = @0;
        animation.toValue = @1;
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        animation.removedOnCompletion = YES;
        [self.pieLayer.mask addAnimation:animation forKey:@"circleAnimation"];
    }
}

@end

@implementation WPieChartDataItem
+ (instancetype)dataItemWithValue:(CGFloat)value color:(UIColor*)color
{
    WPieChartDataItem *item = [WPieChartDataItem new];
//    item.value = value >= 1 ? value : 1;
    item.value = value;
    item.color  = color;
    return item;
}
@end